/**
 * @p.md
 * 
 * 本地集群提供者
 * 提供在单机环境下的集群功能
 */
import { EventEmitter } from 'events';
import { 
  ClusterProvider, 
  ClusterProviderEvent, 
  ClusterProviderEventType 
} from '../clusterProvider';
import { Cluster } from '../cluster';
import { Member, MemberStatus } from '../clusterConfig';
import crypto from 'crypto';

/**
 * 本地集群提供者配置
 */
export interface LocalProviderConfig {
  /**
   * 心跳间隔(毫秒)
   */
  heartbeatInterval?: number;
  
  /**
   * 检测超时(毫秒)
   */
  monitorTimeout?: number;
  
  /**
   * 是否模拟网络延迟
   */
  simulateNetworkDelay?: boolean;
  
  /**
   * 网络延迟范围(毫秒)
   */
  networkDelayRange?: [number, number];
}

/**
 * 默认本地提供者配置
 */
export const DefaultLocalProviderConfig: LocalProviderConfig = {
  heartbeatInterval: 1000,
  monitorTimeout: 5000,
  simulateNetworkDelay: false,
  networkDelayRange: [50, 200]
};

/**
 * 本地集群提供者
 * 用于在单机环境下模拟集群功能
 */
export class LocalProvider extends EventEmitter implements ClusterProvider {
  /**
   * 集群引用
   */
  private cluster: Cluster | null = null;
  
  /**
   * 成员映射
   */
  private members: Map<string, Member> = new Map();
  
  /**
   * 心跳定时器
   */
  private heartbeatTimer: NodeJS.Timer | null = null;
  
  /**
   * 领导者ID
   */
  private leaderId: string | null = null;
  
  /**
   * 本地节点ID
   */
  private localNodeId: string | null = null;
  
  /**
   * 是否已启动
   */
  private running: boolean = false;
  
  /**
   * 事件监听器列表
   */
  private eventListeners: ((event: ClusterProviderEvent) => void)[] = [];

  /**
   * 构造函数
   * @param config 配置
   */
  constructor(private config: LocalProviderConfig = DefaultLocalProviderConfig) {
    super();
  }

  /**
   * 初始化提供者
   * @param cluster 集群引用
   */
  async init(cluster: Cluster): Promise<void> {
    this.cluster = cluster;
    this.localNodeId = cluster.getNodeId();
    
    // 注册本地节点
    const localMember: Member = {
      id: this.localNodeId,
      address: `local://${this.localNodeId}`,
      host: 'localhost',
      port: 0,
      status: MemberStatus.Alive,
      joinedAt: Date.now(),
      capabilities: {},
      metadata: {}
    };
    
    this.members.set(this.localNodeId, localMember);
    
    // 如果还没有领导者，将本地节点设为领导者
    if (!this.leaderId) {
      this.leaderId = this.localNodeId;
      
      // 触发领导者选举事件
      this.emitEvent({
        type: ClusterProviderEventType.LeaderElected,
        leaderId: this.leaderId,
        timestamp: Date.now()
      });
    }
  }

  /**
   * 启动提供者
   */
  async start(): Promise<void> {
    if (this.running) {
      return;
    }
    
    // 开始心跳检测
    this.startHeartbeat();
    
    this.running = true;
  }

  /**
   * 关闭提供者
   */
  async shutdown(): Promise<void> {
    if (!this.running) {
      return;
    }
    
    // 停止心跳检测
    this.stopHeartbeat();
    
    // 清空成员列表
    this.members.clear();
    
    this.running = false;
    this.cluster = null;
    this.leaderId = null;
  }

  /**
   * 注册成员
   * @param address 地址
   * @param metadata 元数据
   */
  async registerMember(address: string, metadata?: any): Promise<void> {
    if (!this.localNodeId) {
      throw new Error('提供者尚未初始化');
    }
    
    const existingMember = this.members.get(this.localNodeId);
    if (existingMember) {
      // 更新现有成员
      existingMember.status = MemberStatus.Alive;
      existingMember.address = address;
      if (metadata) {
        existingMember.metadata = { ...existingMember.metadata, ...metadata };
      }
      this.members.set(this.localNodeId, existingMember);
    } else {
      // 创建新成员
      const member: Member = {
        id: this.localNodeId,
        address,
        host: 'localhost',
        port: 0,
        status: MemberStatus.Alive,
        joinedAt: Date.now(),
        capabilities: {},
        metadata: metadata || {}
      };
      this.members.set(this.localNodeId, member);
    }
    
    // 触发成员加入事件
    this.emitEvent({
      type: ClusterProviderEventType.MemberJoined,
      member: this.members.get(this.localNodeId)!,
      timestamp: Date.now()
    });
    
    // 触发成员可用事件
    this.emitEvent({
      type: ClusterProviderEventType.MemberAvailable,
      member: this.members.get(this.localNodeId)!,
      timestamp: Date.now()
    });
  }

  /**
   * 取消注册成员
   */
  async unregisterMember(): Promise<void> {
    if (!this.localNodeId) {
      return;
    }
    
    const member = this.members.get(this.localNodeId);
    if (!member) {
      return;
    }
    
    // 修改状态为离开
    member.status = MemberStatus.Leaving;
    this.members.set(this.localNodeId, member);
    
    // 触发成员不可用事件
    this.emitEvent({
      type: ClusterProviderEventType.MemberUnavailable,
      member,
      timestamp: Date.now()
    });
    
    // 如果是领导者，选择新的领导者
    if (this.leaderId === this.localNodeId) {
      this.electNewLeader();
    }
    
    // 延迟后真正移除成员
    setTimeout(() => {
      if (this.members.has(this.localNodeId!)) {
        const memberToRemove = this.members.get(this.localNodeId!);
        this.members.delete(this.localNodeId!);
        
        // 触发成员离开事件
        if (memberToRemove) {
          this.emitEvent({
            type: ClusterProviderEventType.MemberLeft,
            member: memberToRemove,
            timestamp: Date.now()
          });
        }
      }
    }, this.getSimulatedDelay());
  }

  /**
   * 获取所有成员
   */
  async getMembers(): Promise<Member[]> {
    return Array.from(this.members.values());
  }

  /**
   * 根据ID获取成员
   * @param memberId 成员ID
   */
  async getMemberById(memberId: string): Promise<Member | null> {
    return this.members.get(memberId) || null;
  }

  /**
   * 监控成员状态变化
   */
  monitorMemberStatusChanges(): void {
    // 本地提供者通过心跳机制实现监控
    // 这个方法在本地实现中不需要额外操作
  }

  /**
   * 获取集群元数据
   */
  async getClusterMetadata(): Promise<any> {
    return {
      memberCount: this.members.size,
      leaderId: this.leaderId,
      providerType: 'local'
    };
  }

  /**
   * 检查是否为领导者
   */
  async isLeader(): Promise<boolean> {
    return this.localNodeId === this.leaderId;
  }

  /**
   * 获取领导者
   */
  async getLeader(): Promise<Member | null> {
    if (!this.leaderId) {
      return null;
    }
    return this.members.get(this.leaderId) || null;
  }

  /**
   * 注册事件监听器
   * @param listener 监听器函数
   */
  registerEventListener(listener: (event: ClusterProviderEvent) => void): void {
    this.eventListeners.push(listener);
  }

  /**
   * 移除事件监听器
   * @param listener 监听器函数
   */
  removeEventListener(listener: (event: ClusterProviderEvent) => void): void {
    const index = this.eventListeners.indexOf(listener);
    if (index !== -1) {
      this.eventListeners.splice(index, 1);
    }
  }

  /**
   * 开始心跳检测
   */
  private startHeartbeat(): void {
    const interval = this.config.heartbeatInterval || DefaultLocalProviderConfig.heartbeatInterval!;
    this.heartbeatTimer = setInterval(() => this.performHeartbeat(), interval);
  }

  /**
   * 停止心跳检测
   */
  private stopHeartbeat(): void {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
    }
  }

  /**
   * 执行心跳检测
   */
  private performHeartbeat(): void {
    // 在真实场景中，这里应该联系其他节点进行状态同步
    // 在本地模拟中，我们只检查节点状态
    
    // 如果没有领导者，选举一个
    if (!this.leaderId || !this.members.has(this.leaderId)) {
      this.electNewLeader();
    }
  }

  /**
   * 选举新领导者
   */
  private electNewLeader(): void {
    // 从活跃节点中选择一个作为领导者
    const aliveMembers = Array.from(this.members.values())
      .filter(m => m.status === MemberStatus.Alive);
    
    if (aliveMembers.length === 0) {
      this.leaderId = null;
      return;
    }
    
    // 选择一个随机的活跃节点作为领导者
    const randomIndex = Math.floor(Math.random() * aliveMembers.length);
    this.leaderId = aliveMembers[randomIndex].id;
    
    // 触发领导者选举事件
    this.emitEvent({
      type: ClusterProviderEventType.LeaderElected,
      leaderId: this.leaderId,
      timestamp: Date.now()
    });
  }

  /**
   * 发送事件给所有监听器
   * @param event 事件对象
   */
  private emitEvent(event: ClusterProviderEvent): void {
    // 应用网络延迟模拟
    if (this.config.simulateNetworkDelay) {
      setTimeout(() => {
        this.eventListeners.forEach(listener => listener(event));
      }, this.getSimulatedDelay());
    } else {
      this.eventListeners.forEach(listener => listener(event));
    }
  }

  /**
   * 获取模拟的网络延迟
   */
  private getSimulatedDelay(): number {
    if (!this.config.simulateNetworkDelay) {
      return 0;
    }
    
    const [min, max] = this.config.networkDelayRange || DefaultLocalProviderConfig.networkDelayRange!;
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }
} 